home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / editor / gsar110.zip / ARG_FUNC.C next >
C/C++ Source or Header  |  1996-08-08  |  9KB  |  244 lines

  1. /* arg_func.c ************************************** updated: 960801.15:39 TT
  2.  *
  3.  * Import      : #includes 
  4.  * Export      : global functions
  5.  * Description : functions for parsing the command line and getting
  6.  *               arguments from the environment
  7.  * Author      : Tormod Tjaberg
  8.  *
  9.  * Note: 
  10.  * Not all programs may want both GetOpt and GetEnvArgs. Therefore I have
  11.  * included special ifdef's for easy inclusion/exclusion.
  12.  * 
  13.  * define NO_GETOPT      ; if you don't want GetOpt
  14.  * define NO_GETENVARG   ; if you don't want GetEnvArgs
  15.  *
  16.  * The default is both functions
  17.  *
  18.  * Copyright (C) 1992-96 Tormod Tjaberg
  19.  * This is free software, distributed under the terms of the
  20.  * GNU General Public License. For details see the file COPYING
  21.  */
  22.  
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <ctype.h>
  26. #include <string.h>
  27. #include "arg_func.h"
  28.  
  29. /* gsar does not parse the environment 
  30.  */
  31. #define NO_GETENVARG
  32.  
  33. #ifndef NO_GETOPT
  34.  
  35. /* variables used by GetOpt
  36.  */
  37. int   OptInx = 1;             /* index into argv, skip argv[0]; filename */
  38. int   CurOpt;                 /* current option checked for validity */
  39. char  *pOptArg;               /* argument associated with option */
  40.  
  41.  
  42. /* GetOpt()
  43.  *
  44.  * Input  : argc - number of arguments on the command line
  45.  *          argv - pointer to the argument vector
  46.  *          pOptStr - pointer to a string containing valid option characters
  47.  * Returns: Current option being processed or an error
  48.  *
  49.  * Scan elements of argv (length is argc) for option characters given in
  50.  * 'pOptStr'. Each time GetOpt is called it returns the next option character
  51.  * from the option elements. When there are no more option charactes left
  52.  * GetOpt returns EOF.
  53.  *
  54.  * 'pOptStr' is a string containing all valid option characters. If an option
  55.  * character is encountered that is not in 'pOptStr', GetOpt returns:
  56.  * BAD_CHAR. The offending character is stored in 'CurOpt'.
  57.  *
  58.  * If a character in the option string is followed by a colon, it means
  59.  * that this option requires an argument. The argument can be the remainding
  60.  * text in the current argv element, or the next argv element. The argument
  61.  * is returned in 'pOptArg'. If no argument was found GetOpt returns:
  62.  * MISSING_ARG and 'pOptArg' is set to NULL. 'CurOpt' contains the offending
  63.  * option char.
  64.  *
  65.  * If a character is followed by two colons it means that this option
  66.  * wants an optional argument. If there is any text left in the current argv
  67.  * element it is returned in 'pOptarg'. If no argument was found 'pOptArg'
  68.  * is set to NULL and the option character is returned.
  69.  *
  70.  * If the option string contains '|' EOF will not be returned when a
  71.  * non option if found. Instead GetOpt returns '|'. If '|' is not specified
  72.  * NON_OPT is returned. In both cases 'pGetOpt' will poin to the non option.
  73.  * and 'OptInx' is the index of argv that contains the non option.
  74.  *
  75.  * Note, the following command line arguments have a special meaning:
  76.  *
  77.  * '-' : GetOpt returns: MISSING_OPT, 'pOptArg' is set to NULL
  78.  * '--': Forces an end of option scanning. GetOpt returns: EOF
  79.  *       Can be detected by checking if `OptInx' != argc, argv[OptInx]
  80.  *       points to the argv element following the '--'
  81.  *
  82.  * Heavily inspired by the UN?X getopt, but a bit simpler
  83.  */
  84. int GetOpt(int argc, char **argv, char *pOptStr)
  85. {
  86.    static char *pCurOpt = "";  /* pointer to current option */
  87.    char        *pOptChar;      /* pointer to char in option string */
  88.  
  89.    if (*pCurOpt == '\0')     /* get a new pointer */
  90.    {
  91.       if (OptInx >= argc)   /* no more of arguments on command line */
  92.          return EOF;
  93.  
  94.       pCurOpt = argv[OptInx];
  95.  
  96.       if (*(pCurOpt++) != '-')
  97.       {
  98.          pCurOpt = "";         /* next time, get a new argv */
  99.          pOptArg = argv[OptInx];
  100.          OptInx++;
  101.  
  102.          if (strchr(pOptStr, '|') != NULL)
  103.             return '|';        /* This might be a filename */
  104.          else
  105.             return NON_OPT;
  106.       }
  107.  
  108.       if (*pCurOpt == '\0')
  109.          return MISSING_OPT;
  110.  
  111.       if (*pCurOpt == '-')   /* catch the '--' */
  112.       {
  113.          OptInx++;             /* point to the argument behind '--' */
  114.          return EOF;
  115.       }
  116.    }
  117.  
  118.    CurOpt = *pCurOpt++;        /* CurOpt is the option character */
  119.  
  120.    if ((pOptChar = strchr(pOptStr, CurOpt)) == NULL)
  121.       return BAD_CHAR;         /* char not in option string, culprit in CurOpt */
  122.  
  123.    if (*(++pOptChar) != ':') /* option doesn't need argument */
  124.    {
  125.       pOptArg = NULL;
  126.       if (*pCurOpt == '\0')
  127.          ++OptInx;
  128.    }
  129.    else
  130.    {                           /* option needs an argument, but how bad ? */
  131.       if (*pCurOpt != '\0')   /* remainder of argv is argument -d123 -> arg = 123 */
  132.          pOptArg = pCurOpt;
  133.       else
  134.          if (*(++pOptChar) == ':') /* '::' optional arg, but no argument */
  135.             pOptArg = NULL;
  136.          else                        /* nothing behind option check next arg */
  137.          {
  138.             if (argc <= ++OptInx)
  139.             {
  140.                pOptArg = NULL;       /* no arguments left but we needed one */
  141.                return MISSING_ARG;   /* return missing arg for option, culprit in CurOpt */
  142.             }
  143.             else                     /* white space separating arguments */
  144.                pOptArg = argv[ OptInx ];
  145.          }
  146.  
  147.       pCurOpt = "";                  /* next time get a new argv */
  148.       ++OptInx;                      /* next argv */
  149.    }
  150.    return CurOpt;                    /* return option letter */
  151. }
  152.  
  153. #endif
  154.  
  155. #ifndef NO_GETENVARG
  156. /* GetEnvArgs()
  157.  *
  158.  * Input  : argc - number of arguments on the command line
  159.  *          argv - pointer to the argument vector
  160.  *          pEnvVar - environment variable we are to find
  161.  * Returns: Number of arguments found in environment
  162.  *
  163.  * Create a new arvector with the enviroment arguments before the
  164.  * program arguments. This way a command line option will override
  165.  * the environment option. Any number of args can be given since we
  166.  * malloc the new argument vector. The environment variable is not destroyed.
  167.  *
  168.  * This code originally used realloc, and did not make a copy of the
  169.  * environment variable.
  170.  */
  171. int GetEnvArgs(int *argc, char ***argv, char *pEnvVar)
  172. {
  173.    char  *pEnvStr;      /* pointer to environment string */
  174.    char  **pArgV;       /* pointer to our new argument vector */
  175.    char  **pStartArgV;  /* pointer to our new argument vector */
  176.    char  *cp;           /* character pointer */
  177.    char  *pBuf;         /* pointer to copy of environment string */
  178.    int count = 0;
  179.    int envcount = 0;
  180.    unsigned char ch;
  181.  
  182.    /* fetch contents of environment variable, if any */
  183.    pEnvStr = getenv(pEnvVar);
  184.  
  185.    if (pEnvStr == NULL || *pEnvStr == 0)
  186.       return 0 ;
  187.  
  188.    while (isspace(*pEnvStr)) /* avoid adding whitespace onto pArgV */
  189.       pEnvStr++;
  190.  
  191.    if ((pBuf = (char *) malloc(1 + strlen(pEnvStr))) == NULL)
  192.       Abort("error: unable to malloc memory for copy of environment string");
  193.  
  194.    strcpy(pBuf,pEnvStr);     /* copy the original string into buffer */
  195.  
  196.    /* count how many arguments there are... so we can malloc */
  197.    cp = pBuf;
  198.    while(*cp != '\0')        /* traverse environment string  */
  199.    {
  200.       while (!isspace(*cp) && *cp != '\0')
  201.          cp++;
  202.       while (isspace(*cp))
  203.          cp++;
  204.       count++;
  205.    }
  206.  
  207.    if (count == 0)           /* if environment string is empty */
  208.       return 0;
  209.  
  210.    envcount = count;
  211.  
  212.    /* malloc a vector that will hold all args + 1 to hold NULL */
  213.    if ((pArgV = pStartArgV = (char **) malloc((count + *argc + 1) * sizeof(char *))) == NULL)
  214.       Abort("error: unable to malloc for arguments");
  215.  
  216.    *(pArgV++) = *((*argv)++);  /* copy argv[0] (filename) from argv */
  217.  
  218.    do
  219.    {
  220.       *(pArgV++) = pBuf;       /* assign argument to new arg vector */
  221.       while ((ch = *pBuf) != '\0' && !isspace(ch))
  222.          pBuf++;               /* step over the argument */
  223.       if (ch != '\0')
  224.          *(pBuf++) = '\0';     /* create a null terminated string */
  225.       while ((ch = *pBuf)